/**
 * 
 */
package com.testing.http.related.restful;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.lang.StringUtils;

/**
 * @author Jason
 *
 */
public class HttpClientRSTester {
	
	/**
	 * sort of Factory method
	 * @return
	 */
	public static HttpClient createClient() {
		return new HttpClient();
	}
	
	/**
	 * factory method for creating the XXXMethod object instance
	 * @param pType
	 * @param pUrl
	 * @return
	 */
	public static HttpMethod createMethodByType(final String pType, final String pUrl) {
		HttpMethod aMtd=null;
		
		if (StringUtils.isNotBlank(pType)) {
			if (pType.equalsIgnoreCase("get")) {
				aMtd=new GetMethod(pUrl);
				
			} else if (pType.equalsIgnoreCase("post")) {
				aMtd=new PostMethod(pUrl);
				
			} else if (pType.equalsIgnoreCase("delete")) {
				aMtd=new DeleteMethod(pUrl);
			}
		}
		return aMtd;
	}
	
	/**
	 * execute a get method (assume all parameters on the given method's url....)
	 * @param pClient
	 * @param pMtd
	 * @param pArgs
	 * @return
	 */
	public String executeGetMethod(final HttpClient pClient, final GetMethod pMtd, Map<String, Object> pArgs) {
		String aValue=null;
		BufferedReader aReader=null;
		
		if (pClient!=null && pMtd!=null) {
			try {
				StringBuilder aSB=new StringBuilder(1000);
				int aStatus=-1;
				
				aStatus=pClient.executeMethod(pMtd);
				if (aStatus!=HttpStatus.SC_OK) {
					throw new RuntimeException("[executeGetMethod] seems trouble: http status => "+aStatus);
				}
				// read the body... 3 fashion a) stream b) string c) byte[]
				aReader=new BufferedReader(new InputStreamReader(pMtd.getResponseBodyAsStream()));
				while((aValue=aReader.readLine())!=null) {
					aSB.append(aValue).append("\r\n");
				}
				
				aValue=aSB.toString();
				
			} catch(Exception e) {
				throw new RuntimeException("[executeGetMethod][execution error~]", e);
				
			} finally {
				if (aReader!=null) {
					try { aReader.close(); }catch(Exception e) {}
				}
				if (pMtd!=null) {
					pMtd.releaseConnection();
				}
			}
		}
		return aValue;
	}
	
	/**
	 * execute a post method (assume parameters need to be set and given by the pArgs parameter)
	 * @param pClient
	 * @param pMtd
	 * @param pArgs
	 * @return
	 */
	public String executePostMethod(final HttpClient pClient, final PostMethod pMtd, Map<String, Object> pArgs) {
		String aValue=null;
		BufferedReader aReader=null;
		
		if (pClient!=null && pMtd!=null) {
			try {
				StringBuilder aSB=new StringBuilder(1000);
				int aStatus=-1;
				
				/*
				 * set Post/ form parameters
				 */
				if (pArgs!=null && !pArgs.isEmpty()) {
					Set<Entry<String, Object>> aEntries=pArgs.entrySet();
					for (Entry<String, Object> aEntry:aEntries) {
						pMtd.addParameter(aEntry.getKey(), (String) aEntry.getValue());
					}
				}
				/*
				 * debug....
				 */
				NameValuePair[] aParams=pMtd.getParameters();
				for (NameValuePair aParam:aParams) {
					aSB.append(aParam.getName()).append(" -- ").append(aParam.getValue()).append("\r\n");
				}
				System.out.println("Params set for PostMethod::\r\n"+aSB.toString());
				aSB.delete(0, aSB.length());
				
				/*
				 * execute the PostMethod
				 */
				aStatus=pClient.executeMethod(pMtd);
				if (aStatus!=HttpStatus.SC_OK) {
					throw new RuntimeException("[executePostMethod] seems trouble: http status => "+aStatus);
				}
				// read the body... 3 fashion a) stream b) string c) byte[]
				aReader=new BufferedReader(new InputStreamReader(pMtd.getResponseBodyAsStream()));
				while((aValue=aReader.readLine())!=null) {
					aSB.append(aValue).append("\r\n");
				}
				
				aValue=aSB.toString();
				
			} catch(Exception e) {
				throw new RuntimeException("[executePostMethod][execution error~]", e);
				
			} finally {
				if (aReader!=null) {
					try { aReader.close(); }catch(Exception e) {}
				}
				if (pMtd!=null) {
					pMtd.releaseConnection();
				}
			}
		}
		return aValue;
	}
	
}
